﻿function TimeLine(config) {
    this.config = config;
    this.ajax = null;
    this.ws = null;
    
    
    
    this.Records = []; //录像片段记录
    this.Labels = [];  // 报警片段记录

    this.drawBegin = Date.parse("1970/1/1 00:00:00");
    this.drawEnd = Date.parse("1970/1/1 23:59:59");

    this.currentPlay = null; //当前正在播放录像的开始时间 毫秒数

    this.LINE = null;  // dvr 播放时 鼠标移入的提示线
    this.ELEMENT = null;// dvr 播放时 鼠标移入的提示文字 

    this.drawEndTime = 0;//录像返回最后的结束时间

    this.cb_queryFinish = config.cb_queryFinish;
    this.cb_timelinePick = config.cb_timelinePick;
    this.cb_lablePick = config.cb_lablePick;

    this.currentPlayOpt = null;

    if (config.docElement) {
        this.draw = SVG(config.docElement).size("100%", "100%");
        
    }


    if (config.videoElement && !config.singleVideo) {
        TimeLine.timelines[config.videoElement] = this;
    }
    return this;
}
TimeLine.prototype = {
    constructor: TimeLine,
    abort: function () {
        try {
            if (this.ajax && this.ajax.abort) {
                this.ajax.abort();
            } else if (this.ws && this.ws.close) {
                this.ws.close();
            }
        } catch (e) {

        }
    },
    Query: function () { //查询数据 返回录像片段
        var reg=/(\d{4}-\d{1,2}-\d{1,2}).*/g;
        var cameraId = this.config.cameraId;
        var videoElement = this.config.videoElement;
        var playWay = this.config.playWay;
        

        var beginTime = this.config.beginTime.replace(/\//g, "-");// xxxx-YY-dd hh:mm:ss

        var endTime = this.config.endTime ? this.config.endTime.replace(/\//g,"-"): beginTime.replace(reg, "$1 23:59:59");
        

        var dvr_beginTime = beginTime.replace(/(\s+|:)/g, "-"); // xxxx-YY-dd-hh-mm-ss
        var dvr_endTime = endTime.replace(/(\s+|:)/g, "-");

        this.drawBegin = new Date(beginTime.replace(/-/g, "/")).getTime();
        this.drawEnd = new Date(endTime.replace(/-/g, "/")).getTime();

        this.beginTime = beginTime;
        this.endTime = endTime;

      
        var dvrUrl = '/querydvr.ws?begintime=' + dvr_beginTime + '&cameraid=' + cameraId + '&endtime=' + dvr_endTime;

        dvrUrl = this.config.MEDIASERVERIP_ws + dvrUrl;

        var nvrUrl = '/Query/QueryRecords?api=root&beginTime=' + beginTime + '&cameraId=' + cameraId + '&endTime=' + endTime;
        var nvrSignURI = TimeLine.MakeSign(nvrUrl, "pass");
        nvrUrl = this.config.MEDIASERVERIP + nvrUrl + "&sign=" + nvrSignURI;

        var _this = this;
        if (playWay == "nvr") {
            this.ajax = $.ajax({
                url: nvrUrl,
                cache: false
            }).done(function (result) {
               
                if (result.length > 0) {
                    _this.Records = JSON.parse(result);
                    if (_this.config.docElement) {
                        _this.draw.clear();
                        _this.drawRects();
                        _this.drawTime();
                        _this.QueryLables();  
                    }
                   
                                     
                }
                _this.GetNext();               
                if (_this.cb_queryFinish) {
                    _this.cb_queryFinish();
                }
            }).fail(function (XMLHttpRequest, textStatus, errorThrown) {
                console.log("获取nvr录像片段失败");
                if (_this.config.docElement) {
                    var came_box = document.querySelector("#" + videoElement);
                    came_box.innerHTML = "<h5 class='error text-center' style='margin:0;padding-top:30px;color:#fff;'>获取nvr方式录像片段失败 " + nvrUrl + "  " + textStatus + "  " + errorThrown + "</h5>";
                }
            })
            
        } else { //dvr
            var ws = new WebSocket(dvrUrl);
            this.ws = ws;
            ws.onclose = function () { console.log("dvr websocket 关闭") };
            ws.onerror = function () {
                console.log("websocket获取dvr播放片段失败", dvrUrl);
                ws.close();
                if (_this.config.docElement) {
                    var came_box = document.querySelector("#" + videoElement);
                    came_box.innerHTML = "<h5 class='error text-center' data-videoelement='" + videoElement + "' style='margin:0;padding-top:10px;color:#fff;'>dvr获取录像片段失败<span class='stopVideo' style='color: #fff;cursor:pointer;text-decoration:underline;'>关闭</span></h5>";
                }
            }
            ws.onopen = function () { }
            ws.onmessage = function (data) {
                var result = data.data;
                if (result.length > 0) {
                    Records = JSON.parse(result); console.log(Records);
                    _this.Records = Records;
                    if (_this.config.docElement) {
                        _this.draw.clear();
                        _this.drawRects();
                        _this.drawTime();
                    }
                    //if (!Records.length){
                    //    console.log("录像回放片段为空");
                    //    var came_box = document.querySelector("#" + videoElement);
                    //    came_box.innerHTML = "<h5 class='error text-center' style='margin:0;padding-top:30px;color:#fff;'>录像片段为空 " + dvrUrl + "</h5>";
                    //}
                }
                ws.close();
                _this.GetNext();
		
				if (_this.cb_queryFinish) {
                    _this.cb_queryFinish();
                }
            }
        }
        return this;
    },
    drawRects: function() { //绘制录像
        this.draw.rect("100%", 40).attr({ fill: '#474747' });//背景
        var playWay = this.config.playWay;
        var docElement = this.config.docElement;
        var Records = this.Records;
        var drawBegin = this.drawBegin;
        var drawEnd = this.drawEnd;
        var draw = this.draw;

        
        var W = document.getElementById(docElement).offsetWidth;

        this.PlayProgressLine = draw.line(0, 0, 0, 40).stroke({ width: 1, color: '#fffc00' }); // 播放总进度线

        this.LINE = draw.line(0, 0, 0, 40).stroke({ width: 2, color: '#f06' }).hide(); //鼠标移入的提示指示线
        this.ELEMENT = draw.plain().stroke({ "color": "#fff", "size": 10 }).hide();   // 鼠标移入的提示文字
        

        var LINE = this.LINE;
        var ELEMENT = this.ELEMENT;

        var _this = this;
        $.each(Records, function (i, value) {
            
           
            var bt = new Date(value.begintime.replace(/-/g, "/")).getTime();
            var oldbt = bt;
            value.serverBegintm = oldbt; // 从服务器中真正返回的开始时间

            
            var et = new Date(value.endtime.replace(/-/g, "/")).getTime();
            et > _this.drawEndTime && (_this.drawEndTime = et);
               
            if (et >= drawBegin && bt <= drawEnd) { //在时间范围内
                
                value.seek = drawBegin - bt > 0 ? (bt - drawBegin)/1000: 0;

                if (bt < drawBegin) {
                    bt = drawBegin;
                    if (playWay == "dvr") {
                        value.begintime = _this.beginTime;
                    }
                }
                if (et > drawEnd) et = drawEnd;

                var x = (bt - drawBegin) * 100 / (drawEnd - drawBegin) + "%";
                var w = (et - bt) * 100 / (drawEnd - drawBegin) + "%";
                var h = _this.config.height - 14;

                var rect = draw.rect(w, h).move(x, 14).fill("#71D332");

                
                var disTime = 2 * 60000; // 时间相差 2 分钟

                rect.click(function (e) {
                    
                    var begintime = new Date(bt);
                    var currentPlay = bt;
                    var W = document.getElementById(docElement).offsetWidth;
                    var seek = 0; 
                    try {
                        
                        var offsetX = e.offsetX;
                        
                        var begintimeNum = offsetX * (drawEnd - drawBegin) / W + drawBegin;
                       
                        if (begintimeNum > et) { begintimeNum = et; }

                        if (begintimeNum < bt) { begintimeNum = bt; }

                        currentPlay = begintimeNum;
                        begintime = new Date(begintimeNum);

                        seek = (begintimeNum - oldbt) / 1000;
                        
                    } catch (err) {

                    }
                                  
                    _this.currentPlay = currentPlay;
                    begintime = begintime.getFullYear() + "-" + (begintime.getMonth() + 1) + "-" + begintime.getDate() + " " + begintime.getHours() + ":" + begintime.getMinutes() + ":" + begintime.getSeconds();
                    
                    var data = $.extend(true, {}, value, { seek: seek, begintime: begintime });
                    _this.setCurrentOpt(data);
                    _this.cb_timelinePick();
                   
                });
                rect.mouseover(function () {
                    
                        W = document.getElementById(docElement).offsetWidth;
                        ELEMENT && ELEMENT.show(); LINE && LINE.show();
                    
                    this.style('cursor:pointer;fill:#93F656;');
                });
                rect.mouseout(function () {
                    ELEMENT && ELEMENT.hide(); LINE && LINE.hide();
                    this.style('fill:#71D332;')
                });
                rect.mousemove(function (e) {
                    
                        try {
                            var offsetX = e.offsetX;
                            var begintimeNum = offsetX * (drawEnd - drawBegin) / W + drawBegin;
                            if (begintimeNum > et) { begintimeNum = et }
                            begintime = new Date(begintimeNum);
                            begintime = begintime.getFullYear() + "/" + (begintime.getMonth() + 1) + "/" + begintime.getDate() + " " + begintime.getHours() + ":" + begintime.getMinutes() + ":" + begintime.getSeconds();
                            LINE.stop().animate(40).move(offsetX, 0);
                            var x = offsetX - 66;
                            x = x < 0 ? 0 : (x > W - 100 ? W - 100 : x);
                            ELEMENT.move(x, 0).plain(begintime);
                        } catch (err) {

                        }
                    

                });
            }
        });
    },
    
    drawTime: function () {//时间标
        var drawEnd = this.drawEnd;
        var drawBegin = this.drawBegin;
        var draw = this.draw;

        var diff = (drawEnd - drawBegin) / 1000 / 60; //分钟
        if (diff >= 240) {
            diff = 30; //30分钟 1个标记
        } else if (diff > 60) {
            diff = 15; // 15分钟 1个标记
        } else {
            diff = 5;  //5分钟1个标记
        }

        var day = new Date(drawBegin);
        day.setHours(0);
        day.setMinutes(0);
        day.setSeconds(0);
        day.setMilliseconds(0);
        
        var daytime = day.getTime();
		
        while (daytime <= drawEnd) {
            if (daytime >= drawBegin) {
                //划线
                //console.log(daytime - drawBegin, (daytime - drawBegin) / (drawEnd - drawBegin), (daytime - drawBegin) * Config.width / (drawEnd - drawBegin), (daytime - drawBegin)/ (drawEnd - drawBegin)*100+"%");
                var x = (daytime - drawBegin) * 100 / (drawEnd - drawBegin) + "%";
				
                if (day.getMinutes() == 0) {
                    draw.line(x, 0, x, 6).stroke({ color: '#FFFFFF', width: 1 });
                } else {
                    draw.line(x, 0, x, 3).stroke({ color: '#E0E0E0', width: 1 });
                }
                //文字
                if (diff>=15 && day.getMinutes() == 0 && day.getSeconds() == 0) {
                    var hourtext = day.getHours();
                    var text = draw.text(function (add) {
                        var tx = parseFloat(x) - 0.3;
                        if (tx < 0) tx = 0;
                        if ((tx + 0.6) > 100) tx = 100 - 10;
                        add.tspan(hourtext).dx(tx + "%").dy(14).fill('#FFFFFF');
                    }).size(9);
                }else if(diff < 15) {
					var minutes = day.getMinutes();
					var hourtext = day.getHours()+":"+ (minutes<10? '0'+minutes:minutes );
                    var text = draw.text(function (add) {
                        var tx = parseFloat(x) - 0.3;
                        if (tx < 0) tx = 0;
                        if ((tx + 0.6) > 100) tx = 100 - 10;
                        add.tspan(hourtext).dx(tx + "%").dy(14).fill('#FFFFFF');
                    }).size(9);
					
				}
            }
            //时间+diff
            daytime = day.getTime();
            daytime += (diff * 60000);
            day = new Date(daytime);
        }

    },
    QueryLables: function () { //查询报警数据
       
        var url = '/Query/QueryLabels?api=root&beginTime=' + this.beginTime + '&cameraId=' + this.config.cameraId + '&endTime=' + this.endTime;
        var signURI = TimeLine.MakeSign(url, "pass");
        url = this.config.MEDIASERVERIP + url + "&sign=" + signURI;
        var _this = this;
        $.ajax({
            type: "GET",
            url: url,
            cache: false,
            success: function (result) {
                console.log(result);
                _this.Labels = JSON.parse(result);
                _this.drawLines();
            }
        });
    },
    drawLines: function () { // 绘制报警线 以及绑定对应事件
        var _this = this;
        var drawBegin = this.drawBegin;
        var drawEnd = this.drawEnd;
        var draw = this.draw;

        $.each(this.Labels, function (i, value) {
            var t = Date.parse(value.labeltime);
            var oldbt = Date.parse(value.begintime);
            value.serverBegintm = oldbt; // 从服务器中真正返回的开始时间

            if (t >= drawBegin && t < drawEnd) {
                var x = (t - drawBegin) * 100 / (drawEnd - drawBegin) + "%";
                var h = Config.height - 14;
                var line = draw.rect(3, h).move(x, 14).fill('#FEEB88');

                value.seek = (t - oldbt) / 1000;

                line.mouseover(function () { this.style('fill:#E2353D;'); });
                line.mouseout(function () { this.style('fill:#FEEB88;') });

                line.click(function () {
                    if (_this.config.cb_lablePick) {
                        var currentPlay = Date.parse(value.labeltime);
                        _this.currentPlay = currentPlay;
                        
                        _this.setCurrentOpt(value);
                        _this.cb_lablePick();
                        
                    }
                });
            }
        });
    },
    
    setCurrentOpt: function (opt) {
        if (opt) {
            opt.came_name = this.config.came_name;
            opt.videoElement = this.config.videoElement;
            opt.playWay = this.config.playWay;
            opt.cameraId = this.config.cameraId;
            opt.queryBeginTime = this.beginTime;
            opt.queryEndTime = this.endTime;  // 查询的结束时间 查询日期的 年-月-日 23:59:59
            opt.drawEndTime = this.drawEndTime;// 返回录像片段的最终实际结束时间 毫秒数
            opt.config = this.config;
        }
       
        this.currentPlayOpt = opt;
    },
    initDraw: function () {
        this.draw.clear();
        this.draw = SVG(this.config.docElement).size("100%", "40");
        this.drawRects();
        this.drawTime();
        this.drawLines();
    },
    Clear: function () {
        this.Records = [];
        this.Labels = [];
        this.drawBegin = Date.parse("1970/1/1 00:00:00");
        this.drawEnd = Date.parse("1970/1/1 23:59:59");
        this.currentPlay = undefined;
        this.draw.clear();
        this.drawRects();
        this.drawTime();

    },
    GetNext: function () {
        var ret = undefined,t;
        var Records = this.Records;
        var currentPlay = this.currentPlay;
        for (var i = 0; i < Records.length; i++) {
            t = Date.parse(Records[i].begintime);
            if (currentPlay == undefined || currentPlay == null || t > currentPlay) {
                this.currentPlay = t;
                this.setCurrentOpt(Records[i]);
                return;
            }
        }
        this.setCurrentOpt(null);        
    },
    GetNextAlarm: function () {
        var t, value;
        var Labels = this.Labels;
        var currentPlay = this.currentPlay;
        for (var i = 0; i < Labels.length; i++) {
            value = Labels[i];
            t = Date.parse(value.labeltime);
            if (currentPlay == undefined || currentPlay == null || t > currentPlay) {
                this.currentPlay = t;
                
                this.setCurrentOpt(value);
                    
                return;
            }
        }
        this.setCurrentOpt(null);
    },
    GetPrevious: function () {
        var ret = undefined;
        var Records = this.Records;
        var currentPlay = this.currentPlay;
        for (var i = Records.length - 1; i >= 0; i--) {
            var t = Date.parse(Records[i].endtime);
            if (currentPlay == undefined || currentPlay == null || t < currentPlay) {
                this.currentPlay = t;
                this.setCurrentOpt(Records[i]);
                //ret = { filename: Records[i].filename, begintime: Records[i].begintime, endtime: Records[i].endtime, seek: 0, playWay: Config.playWay, cameraId: Config.cameraId, SearchDate: Config.SearchDate };
                //break
                return ;
            }
        }
        this.setCurrentOpt(null);
    },
    GetPreviousAlarm: function () {
        var ret = undefined;
        var Labels = this.Labels;
        var currentPlay = this.currentPlay;
        for (var i = Labels.length - 1; i >= 0; i--) {
            var t = Date.parse(Labels[i].labeltime);
            if (currentPlay == undefined || currentPlay == null || t < currentPlay) {
                this.currentPlay = t;
                //var begin = Date.parse(Labels[i].begintime);
                //var seektime = (currentPlay - begin) / 1000;
                //ret = { filename: Labels[i].filename, begintime: Labels[i].labeltime, seek: seektime, playWay: Config.playWay, cameraId: Config.cameraId, SearchDate: Config.SearchDate };

                //value.seek = (t - Date.parse(Labels[i].begintime) ) / 1000;
                this.setCurrentOpt(value);

                return;
            }
        }
        this.setCurrentOpt(null);
    },
    ChangeShowRange:function (beginTime, endTime) {
        this.drawBegin = Date.parse(beginTime);
        this.drawEnd = Date.parse(endTime);
        this.drawTime();
        this.drawRects();
        this.drawLines();
    },
    PlayProgress: function (datetimeNum) {
        var drawBegin = this.drawBegin;
        var drawEnd = this.drawEnd;
        

        var x = (datetimeNum - drawBegin) * 100 / (drawEnd - drawBegin) + "%";
        
        this.PlayProgressLine.plot(x, 0, x, 40);
        
    }
}

TimeLine.MakeSign = function (url, apppass) {
   
    //url --要签名的URL,  apppass -- 平台密码
    //url要签名的字符串,参数顺序按首字母升序排列。url中的app=平台用户名, 将url做HmacSHA256散列，散列的加密key是平台密码的MD5值
    var key = $.md5(apppass);
    var signatureSHA = CryptoJS.HmacSHA256(url, key);// token 
    //console.log("signatureSHA:" + signatureSHA);
    var signatureBase64 = CryptoJS.enc.Base64.stringify(signatureSHA); // base64
    //console.log("signatureBase64:" + signatureBase64);
    var signURI = encodeURIComponent(signatureBase64);     // URI编码
    //console.log("signatureBaseURI:" + signURI);
    return signURI;
  
}
TimeLine.CreateHtml = function (playWay, camid, videoelement) {
    
    //var timeline_box = '<div style="position:absolute;bottom:' + (playWay == "nvr" ? "30px" : 0) + ';left:0;width:100%;height:40px;" class="timeline" id="timeline' + camid + '"></div>';

    var btnGroups = '<div class="text-center" style="position:absolute;bottom:0;left:0;width:100%;height:30px;background-color:#fff;"><div data-videoelement="' + videoelement+'" class="btn-group btn-group-sm" role="group">'
        + '<button type="button" class="btn btn-default playPre"  title="上一个录像"><span class="glyphicon glyphicon-fast-backward"></span></button>'
        + '<button type="button" class="btn btn-default playPreAlarm" title="上一个报警录像"><span class="glyphicon glyphicon-step-backward"></span></button>'
        + '<button type="button" class="btn btn-default continueVideo"  title="播放"><span class="glyphicon glyphicon-play"></span></button>'
        + '<button type="button" class="btn btn-default pauseVideo" title="暂停"><span class="glyphicon glyphicon-pause"></span></button>'
        + '<button type="button" class="btn btn-default stopVideo"  title="停止"><span class="glyphicon glyphicon-stop"></span></button>'
        + '<button type="button" class="btn btn-default playNextAlarm"  title="下一个报警录像"><span class="glyphicon glyphicon-step-forward"></span></button>'
        + '<button type="button" class="btn btn-default playNext" title="下一个录像"><span class="glyphicon glyphicon-fast-forward"></span></button>'
        + '</div></div>';

    var str = playWay == "nvr" ? btnGroups : "";
    return str;
}
TimeLine.timelines = {};
TimeLine.ClearAll = function () {
    for (var key in TimeLine.timelines) {
        TimeLine.timelines[key].draw.clear();
        delete TimeLine.timelines[key];
    }
}